﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Windows.Media.Imaging;
using System.Windows.Media;
using System.Windows;
using System.Windows.Forms;
using System.IO;
using System.Windows.Threading;

namespace LetsGoToSchool
{
    static public class Utils
    {
        /// <summary>
        /// returns an image representing the icon of the given 
        /// image file, which needs to be added to Resources beforehand.
        /// </summary>
        /// <param name="filename">String: filename of the image file</param>
        /// <returns> BitmapImage </returns>
        public static BitmapImage getIcon(String filename)
        {
            BitmapImage bit = new BitmapImage();
            bit.BeginInit();
            bit.UriSource = new Uri("pack://application:,,,/Resources/" + filename, UriKind.Absolute);
            bit.EndInit();
            return bit;
        }

        /// <summary>
        /// loads the image from the given path to memory.
        /// </summary>
        /// <param name="path"> String </param>
        /// <returns> the Image object </returns>
        public static Image loadImage(String path) {
            BitmapImage bit = new BitmapImage();
            bit.BeginInit();
            bit.UriSource = new Uri(path, UriKind.Absolute);
            bit.EndInit();

            Image image = new Image();
            image.Stretch = Stretch.Uniform;
            image.Source = bit;
            image.Height = 200;
            return image;
        }

        /// <summary>
        /// change the source of the given Image to the image at the given path
        /// </summary>
        /// <param name="img"> Image </param>
        /// <param name="path"> String </param>
        public static void changeSource(Image img, String path)
        {
            BitmapImage bit = new BitmapImage();
            bit.BeginInit();
            bit.UriSource = new Uri(path, UriKind.Absolute);
            bit.EndInit();

            img.Source = bit;
        }

        /// <summary>
        /// Calculate the distance between 2 points
        /// </summary>
        /// <param name="start"> Point </param>
        /// <param name="end"> Point </param>
        /// <returns> distance square </returns>
        public static double Distance2(Point start, Point end)
        {
            double xDist = start.X - end.X;
            double yDist = start.Y - end.Y;

            return (xDist * xDist) + (yDist * yDist);
        }

        /// <summary>
        /// take screenshot in the given rectangle
        /// </summary>
        /// <param name="bounds"></param>
        /// <returns></returns>
        public static System.Drawing.Bitmap TakeSnapshot(System.Drawing.Rectangle bounds)
        {
            foreach (Screen s in Screen.AllScreens)
                if (s.Bounds.Contains(bounds.Location))
                    return TakeSnapshot(new System.Drawing.Rectangle(bounds.X - s.Bounds.X, bounds.Y - s.Bounds.Y, bounds.Width, bounds.Height), s);
            return null;
        }

        /// <summary>
        /// take screenshot in the given rectangle on the give screen
        /// </summary>
        /// <param name="bounds"></param>
        /// <param name="screen"></param>
        /// <returns></returns>
        public static System.Drawing.Bitmap TakeSnapshot(System.Drawing.Rectangle bounds, Screen screen)
        {
            // add the X and Y properties of the screen's Bounds property, properly orienting the bounds
            // rectangle to the proper display
            if (bounds.Width == 0)
                bounds = screen.Bounds;
            else
            {
                bounds.X += screen.Bounds.X;
                bounds.Y += screen.Bounds.Y;
            }

            if (bounds.X > screen.Bounds.Right || bounds.Y > screen.Bounds.Bottom)
            {
                throw new ArgumentOutOfRangeException("bounds", screen.Bounds,
                                                      "None of the rectangle's area is inside the display area.");
            }

            if (bounds.X + bounds.Width < screen.Bounds.Left || bounds.Y + bounds.Height < screen.Bounds.Top)
            {
                throw new ArgumentOutOfRangeException("bounds", screen.Bounds,
                                                      "None of the rectangle's area is inside the display area.");
            }

            try
            {
                // create a Bitmap the same size as the rectangle given
                System.Drawing.Bitmap image = new System.Drawing.Bitmap(bounds.Width, bounds.Height);

                // create a graphics context for the bitmap
                using (System.Drawing.Graphics graphics = System.Drawing.Graphics.FromImage(image))
                {
                    // fill the bitmap
                    graphics.CopyFromScreen(bounds.X, bounds.Y, 0, 0, bounds.Size, System.Drawing.CopyPixelOperation.SourceCopy);
                }

                // return the result
                return image;
            }
            catch (Exception e)
            {
                throw new Exception("Unexpected errors occur while retrieving the snapshot.", e);
            }
        }

        /// <summary>
        /// convert bitmap
        /// </summary>
        /// <param name="bitmap"></param>
        /// <returns></returns>
        public static BitmapImage LoadImage(this System.Drawing.Bitmap bitmap)
        {
            MemoryStream ms = new MemoryStream();
            bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
            BitmapImage bi = new BitmapImage();
            bi.BeginInit();
            bi.StreamSource = ms;
            bi.EndInit();
            return bi;
        }

        /// <summary>
        /// execute the given action soon
        /// </summary>
        /// <param name="action"></param>
        public static void Soon(Action action)
        {
            DispatcherTimer tmr = new DispatcherTimer();
            tmr.Interval = TimeSpan.FromMilliseconds(50);
            tmr.Tick += delegate(Object sende, EventArgs e)
            {
                tmr.Stop();
                tmr = null;

                action();
            };

            tmr.Start();
        }
    }
}
